package cn.lastcrdg.testverificationcode;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

/**
 * author：liluo
 * e-mail：lastcrazysun@163.com
 * company：cusc
 * date：2017/10/31 14:05
 * description：
 */

public class VerifycodeView extends LinearLayout implements View.OnKeyListener, TextWatcher, View.OnTouchListener {

    private static final String TAG = VerifycodeView.class.getSimpleName();
    private Context mContext;
    private OnInputCompleteListener listener;
    private List<EditText> mEditTextList = new ArrayList<>();

    private int mCurrentPos;
    /**
     * 编辑框的个数
     */
    private int mInputNum;
    /**
     * 编辑框的宽度
     */
    private int mInputWidth;
    /**
     * 编辑框的高度
     */
    private int mInputHeight;
    /**
     * 编辑框水平方向的间距
     */
    private int mInputHPadding;
    /**
     * 编辑框垂直方向的间距
     */
    private int mInputVPadding;
    /**
     * 编辑框没有焦点的样式
     */
    private Drawable mInputMormal;
    /**
     * 编辑框获取焦点时的样式
     */
    private Drawable mInputEdit;

    public VerifycodeView(Context context) {
        this(context, null);
    }

    public VerifycodeView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VerifycodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerifycodeView);
        mInputNum = typedArray.getInt(R.styleable.VerifycodeView_input_number, 4);
        mInputWidth = (int) typedArray.getDimension(R.styleable.VerifycodeView_input_width, mInputWidth);
        mInputHeight = (int) typedArray.getDimension(R.styleable.VerifycodeView_input_height, mInputHeight);
        mInputVPadding = (int) typedArray.getDimension(R.styleable.VerifycodeView_input_v_padding, 0);
        mInputHPadding = (int) typedArray.getDimension(R.styleable.VerifycodeView_input_h_padding, 0);
        mInputMormal = typedArray.getDrawable(R.styleable.VerifycodeView_input_bg_normal);
        mInputEdit = typedArray.getDrawable(R.styleable.VerifycodeView_input_bg_edit);
        typedArray.recycle();
        checkXml();
        init();
    }

    private void checkXml() {
        if (mInputMormal == null || mInputEdit == null) {
            throw new RuntimeException("must in drawable to set mInputMormal and mInputEdit");
        }
        if (mInputNum < 1) {
            throw new RuntimeException("the input_number must > 0");
        }
    }

    private void init() {
        if (mInputWidth == 0 || mInputHeight == 0) {
            mInputWidth = 200;
            mInputHeight = 200;
        }
        LinearLayout.LayoutParams layoutParams = new LayoutParams(mInputWidth, mInputHeight);
        layoutParams.gravity = Gravity.CENTER;
        layoutParams.bottomMargin = mInputVPadding;
        layoutParams.topMargin = mInputVPadding;
        layoutParams.leftMargin = mInputHPadding;
        layoutParams.rightMargin = mInputHPadding;
        for (int i = 0; i < mInputNum; i++) {
            EditText editText = new EditText(mContext);
            editText.setTextColor(Color.BLACK);
            editText.setInputType(EditorInfo.TYPE_CLASS_NUMBER);
            editText.setGravity(Gravity.CENTER);
            editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)});
            setBground(editText, false);
            if (i == 0) {
                layoutParams.leftMargin = 0;
                editText.requestFocus();
                setBground(editText, true);
            }
            if (i == mInputNum - 1) {
                layoutParams.rightMargin = 0;
            }
            editText.setLayoutParams(layoutParams);
            editText.setId(i);
            addView(editText);
            mEditTextList.add(editText);
            editText.setOnKeyListener(this);
            editText.setOnTouchListener(this);
            editText.addTextChangedListener(this);
        }
        setFocusable(false);
        setEnabled(true);
    }

    /**
     * 根据焦点更换背景图片
     *
     * @param editText
     * @param isFocus
     */
    private void setBground(EditText editText, boolean isFocus) {
        if (isFocus) {
            editText.setBackground(mInputEdit);
        } else {
            editText.setBackground(mInputMormal);
        }
    }

    private void setBground(EditText editTextFocus, EditText editTextNoFocus) {
        editTextFocus.setBackground(mInputEdit);
        editTextNoFocus.setBackground(mInputMormal);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LinearLayout.LayoutParams(getContext(), attrs);
    }

    @Override
    public void setEnabled(boolean enabled) {
        for (int i = 0; i < mInputNum; i++) {
            if (enabled) {
                getChildAt(i).setFocusable(true);
                getChildAt(i).setFocusableInTouchMode(true);
            } else {
                getChildAt(i).setFocusable(false);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        for (int i = 0; i < mInputNum; i++) {
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
        }
        View child = getChildAt(0);
        int childWidth = child.getMeasuredWidth();
        int childHeight = child.getMeasuredHeight();
        int maxHeight = childHeight + mInputVPadding * 2;
        int maxWidth = (childWidth + mInputHPadding) * mInputNum - mInputHPadding;
        setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.d(TAG, "onLayout: ");
        for (int i = 0; i < mInputNum; i++) {
            View child = getChildAt(i);
            int width = child.getMeasuredWidth();
            int height = child.getMeasuredHeight();
            int childLeft = i * (width + mInputHPadding);
            int childTop = mInputVPadding;
            int childRight = childLeft + width;
            int childBottom = mInputVPadding + height;
            child.layout(childLeft, childTop, childRight, childBottom);
        }
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        EditText editText_current = (EditText) v;
        if (keyCode == KeyEvent.KEYCODE_DEL) {
            if (mCurrentPos != 0) {
                editText_current.setText("");
                mCurrentPos--;
                EditText editText_last = mEditTextList.get(mCurrentPos);
                editText_last.requestFocus();
                setBground(editText_last, editText_current);
            } else {
                editText_current.setText("");
            }

        }
        return false;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (start == 0 && count > 0 && mCurrentPos < mInputNum - 1) {
            mCurrentPos++;
            EditText editText = mEditTextList.get(mCurrentPos);
            editText.requestFocus();
            setBground(editText, mEditTextList.get(mCurrentPos - 1));
        }
    }

    @Override
    public void afterTextChanged(Editable s) {
            getAllNumber();
    }

    private void getAllNumber() {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < mInputNum; i++) {
            String number = mEditTextList.get(i).getText().toString().trim();
            stringBuilder.append(number);
        }
        if (stringBuilder.length() == mInputNum) {
            hintkeybord();
            EditText editText = mEditTextList.get(mCurrentPos);
            setBground(editText, false);
            editText.clearFocus();
            setEnabled(false);
            mCurrentPos = -1;
        }
        listener.getNumber(stringBuilder.toString().trim());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        EditText editText = (EditText) v;
        setEnabled(true);
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            int id = editText.getId();
            if (id != mCurrentPos) {
                editText.requestFocus();
                if (mCurrentPos == -1) {
                    setBground(editText, true);
                } else {
                    setBground(editText, mEditTextList.get(mCurrentPos));
                }
                mCurrentPos = id;
            }
            return true;
        }
        return false;
    }

    /**
     * 隐藏键盘
     */
    public void hintkeybord() {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(this.getWindowToken(), 0); //强制隐藏键盘
        }
    }

    public interface OnInputCompleteListener {
        void getNumber(String number);
    }

    public void setOnInputCompleteListener(OnInputCompleteListener listener) {
        this.listener = listener;
    }
}
